import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JOptionPane;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.MultivaluedMap;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.GenericType;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.core.util.MultivaluedMapImpl;

public class MiviaMovieClient {
	private MiviaMovieClientFrame frame;
	private Client client;
	private String serverParam = "";

	public MiviaMovieClient() {
		serverParam = JOptionPane.showInputDialog(null,
				"Selezionare ip:porta del server", "localhost:8080");
		client = Client.create();

		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					WebResource availableGenres = client.resource("http://"
							+ serverParam
							+ "/MiviaMovieServer/rest/movies/genres");

					frame = new MiviaMovieClientFrame(serverParam);

					frame.setResources(ResourcesEnum.getAllEnum());

					frame.addQueryExecutorListener(new QueryExecuteListener());
					ClientResponse response = availableGenres.accept(
							"application/xml").get(ClientResponse.class);
					List<MovieType> movieGenres = response
							.getEntity(new GenericType<List<MovieType>>() {
							});

					frame.setMovieTypesList(movieGenres);
					frame.showStatusCode(response.getStatus());

					frame.setVisible(true);
				} catch (Exception e) {
//					e.printStackTrace();
					JOptionPane.showMessageDialog(null,
							"Connessione al server fallita",
							"Errore di connessione", JOptionPane.ERROR_MESSAGE);
				}
			}
		});
	}

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		new MiviaMovieClient();
	}

	private class QueryExecuteListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					ResourcesEnum query = frame.getSelectedQuery();
					WebResource res;
					ClientResponse response;
					List<Movie> movies;
					MultivaluedMap<String, String> queryParams;
					User user;

					switch (query) {

					case MR_getDetailedMovie:
						res = client.resource("http://" + serverParam
								+ "/MiviaMovieServer/rest/movies/"
								+ frame.getMovieID());

						response = res.accept("application/xml").get(
								ClientResponse.class);

						if (response.getStatus() < 300) {
							DetailedMovie detMovie = response
									.getEntity(DetailedMovie.class);
							frame.showDetailedMovie(detMovie);
						} else
							frame.setMessage("Film non trovato");

						frame.showStatusCode(response.getStatus());
						break;
					case MR_getGenres:
						res = client.resource("http://" + serverParam
								+ "/MiviaMovieServer/rest/movies/genres");
						response = res.accept("application/xml").get(
								ClientResponse.class);
						List<MovieType> movieGenres = response
								.getEntity(new GenericType<List<MovieType>>() {
								});
						frame.showMovieTypes(movieGenres);
						break;

					case MR_getMovies:

						res = client.resource("http://" + serverParam
								+ "/MiviaMovieServer/rest/movies");

						queryParams = getQueryParameters();

						res = res.queryParams(queryParams);
						response = res.accept("application/xml").get(
								ClientResponse.class);
						if (response.getStatus() < 300) {
							movies = response
									.getEntity(new GenericType<List<Movie>>() {
									});
							frame.showMovies(movies);
						}
						frame.showStatusCode(response.getStatus());

						break;

					case UR_getMovies:
						response = sendGetMoviesRequest("http://" + serverParam
								+ "/MiviaMovieServer/rest/users/"
								+ frame.getUserID() + "/movies");
						if (response.getStatus() < 300) {
							movies = response
									.getEntity(new GenericType<List<Movie>>() {
									});
							frame.showMovies(movies);
						}
						frame.showStatusCode(response.getStatus());

						break;
						
					case UR_getNews:
						res = client.resource("http://" + serverParam
								+ "/MiviaMovieServer/rest/users/"
								+ frame.getUserID() + "/news");
						response = res.accept("application/xml").get(
								ClientResponse.class);
						
						if (response.getStatus() < 300) {
							movies = response
									.getEntity(new GenericType<List<Movie>>() {
									});
							frame.showMovies(movies);
						}
						frame.showStatusCode(response.getStatus());
						break;
						
					case UR_getRegisteredGenres:
						res = client.resource("http://" + serverParam
								+ "/MiviaMovieServer/rest/users/"
								+ frame.getUserID() + "/genres");
						List<MovieType> types;
						response = res.accept("application/xml").get(
								ClientResponse.class);
						if (response.getStatus() < 300) {
							types = response
									.getEntity(new GenericType<List<MovieType>>() {
									});

							frame.showUser(new User(frame.getUserID(), types));
						}

						frame.showStatusCode(response.getStatus());
						break;

					case UR_registerUser:
						user = frame.getUser();
						if (user != null) {
							res = client.resource("http://" + serverParam
									+ "/MiviaMovieServer/rest/users/");
							response = res.type("application/xml").put(
									ClientResponse.class, user);

							frame.showStatusCode(response.getStatus());
						} else
							frame.setErrorOnParameters();
						break;

					case UR_updateGenres:
						user = frame.getUser();
						if (user != null) {
							res = client.resource("http://" + serverParam
									+ "/MiviaMovieServer/rest/users/"
									+ frame.getUserID() + "/genres");
							response = res.type("application/xml").post(
									ClientResponse.class, new GenericEntity<List<MovieType>>(
											user.getMovieTypes()) {
									});
							frame.showStatusCode(response.getStatus());
						} else
							frame.setErrorOnParameters();
						break;

					}
				}
			}).start();

		}

		private ClientResponse sendGetMoviesRequest(String resourceURL) {
			MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl();

			WebResource res = client.resource(resourceURL);
			if (!frame.getLength().equals(""))
				queryParams.add("length", frame.getLength());

			if (!frame.getStartIndex().equals(""))
				queryParams.add("startIndex", frame.getStartIndex());

			res = res.queryParams(queryParams);
			ClientResponse response = res.accept("application/xml").get(
					ClientResponse.class);

			return response;

		}

		private MultivaluedMap<String, String> getQueryParameters() {
			MultivaluedMap<String, String> params = new MultivaluedMapImpl();

			if (!frame.getActor().equals("")) {
				params.add("actor", frame.getActor());
			}

			if (!frame.getMovieDirector().equals(""))
				params.add("director", frame.getMovieDirector());

			if (!frame.getStartDate().equals("")) {
				params.add("startDate", frame.getStartDate());
			}

			if (!frame.getEndDate().equals("")) {
				params.add("endDate", frame.getEndDate());
			}

			if (!frame.getLength().equals(""))
				params.add("length", frame.getLength());

			if (!frame.getStartIndex().equals(""))
				params.add("startIndex", frame.getStartIndex());

			if (!frame.getTitle().equals(""))
				params.add("title", frame.getTitle());

			if (frame.getMovieTypes().size() > 0) {
				params.put("movieType", frame.getMovieTypes());
			}

			return params;
		}

	}
}

enum ResourcesEnum {
	MR_getMovies, MR_getGenres, MR_getDetailedMovie, UR_registerUser, UR_getRegisteredGenres, UR_updateGenres, UR_getNews, UR_getMovies;

	public static List<ResourcesEnum> getAllEnum() {
		List<ResourcesEnum> queries = new ArrayList<ResourcesEnum>();
		queries.add(MR_getMovies);
		queries.add(MR_getGenres);
		queries.add(MR_getDetailedMovie);
		queries.add(UR_registerUser);
		queries.add(UR_getRegisteredGenres);
		queries.add(UR_updateGenres);
		queries.add(UR_getNews);
		queries.add(UR_getMovies);

		return queries;
	}
}
